#include "StdAfx.h"
#include <MyControls/Percent.h>
#include <string>

namespace My {

template <int D> 
Percent<D>::Percent(float value)
	: m_Value(0) 
{ 
	(* this) = value; 
}

template <int D> 
Percent<D>::Percent(const Percent & rhs)
	: m_Value(rhs.m_Value) 
{ 
}

template <int D> 
Percent<D>::operator float() const
{ 
	return m_Value; 
}

template <int D> 
Percent<D> & Percent<D>::operator = (float value) 
{ 
	if (value < 0)
		value = 0;
	if (value > 1.f)
		value = 1.f;
	if (value != m_Value) {
		m_Value = value;
	}
	return * this;
}

template <int D> 
std::ostream & operator << (std::ostream & out, const Percent<D> & p) 
{
	std::ios::fmtflags f = out.setf(std::ios::fixed, std::ios::floatfield);
	int pr = out.precision(D);
	out << p * 100 << '%';
	out.precision(pr);
	out.flags(f);
	return out;
}

template <int D> 
std::istream & operator >> (std::istream & in, Percent<D> & p)
{
	std::ios::iostate state = std::ios::goodbit;
	const std::istream::sentry ok(in);
    if (ok) {
		try {
			float value;
			std::string units = "%";
			in >> value;
			if (!in.fail()) {
				if (!in.eof())
					in >> units;
				if (in.eof() && units == "%")
					p = value / 100.f;
				else
					state |= std::ios::failbit;
			} else
				state |= std::ios::failbit;
		} catch (...) {
			try {
				in.setstate(std::ios::badbit); 
			} catch (...) { 
			}
			if ((in.exceptions( ) & std::ios::badbit) != 0)
                throw; 
		}
	}
    in.setstate(state);
    return in;
}

template Percent<0>;
template Percent<1>;
template Percent<2>;
template Percent<3>;

template DLL_API std::ostream & operator << (std::ostream &, const Percent<0> &);
template DLL_API std::ostream & operator << (std::ostream &, const Percent<1> &);
template DLL_API std::ostream & operator << (std::ostream &, const Percent<2> &);
template DLL_API std::ostream & operator << (std::ostream &, const Percent<3> &);

template DLL_API std::istream & operator >> (std::istream &, Percent<0> &);
template DLL_API std::istream & operator >> (std::istream &, Percent<1> &);
template DLL_API std::istream & operator >> (std::istream &, Percent<2> &);
template DLL_API std::istream & operator >> (std::istream &, Percent<3> &);

} // My

